﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Samurai.Client.Commands;
using Samurai.Crawler;
using Samurai.DAL;
using Samurai.Infrastructure;
using System.Windows.Threading;

namespace Samurai.Client
{
    public class CrawlDirectoryCommand : ICommand
    {
        private static CrawlDirectoryCommand _instance;

        public static CrawlDirectoryCommand Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new CrawlDirectoryCommand();
                return _instance;
            }
        }

        private CrawlDirectoryCommand()
        {

        }

        Dispatcher _dispatcher;

        public void Execute(object parameter)
        {
            _dispatcher = Dispatcher.CurrentDispatcher;

            var backgroundWorker = new BackgroundWorker();

            backgroundWorker.DoWork += BackgroundWorkerDoWork;

            backgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;

            backgroundWorker.RunWorkerAsync();

        }

        private void FailedWorking(Exception ex)
        {
            _dispatcher.BeginInvoke(new NotifyWorkerFailedDelegate(NotifyWorkerFailed), DispatcherPriority.Normal, ex);
        }
        

        public delegate void NotifyWorkerFailedDelegate(Exception ex);

        private void NotifyWorkerFailed(Exception ex)
        {
            throw ex;
        }

        private static void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            CreateMovieCommand.Instance.Execute(null);
        }

        private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            try
            {

                var locations = Manager.Instance.GetRepositoryLocations();

                var candidateMovies = GetCandidateMoviesFromDirectory(locations.Select(l => l.Location));                

                Manager.Instance.AddCandidateMovies(candidateMovies);
            }


            catch (Exception ex)
            {
                FailedWorking(ex);
            }
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        private static List<CandidateMovie> GetCandidateMoviesFromDirectory(IEnumerable<string> locations)
        {
            var directoryBrowser = new DirectoryBrowser();

            var candidateMovies = new List<CandidateMovie>();

            foreach (var location in locations)
            {
                candidateMovies.AddRange(directoryBrowser.GetCandidateMovies(location));
            }
            return candidateMovies;
        }
    }
}
